package com.wdb007.venus.wss.channelgroup;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import io.netty.channel.Channel;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.ChannelGroupFuture;
import io.netty.channel.group.ChannelMatcher;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import io.netty.util.concurrent.GlobalEventExecutor;

public class AppChannelGroups {

	public static Logger logger = LoggerFactory.getLogger(AppChannelGroups.class);
	
	private static final ChannelGroup APP_CHANNEL_GROUP = new DefaultChannelGroup("bookcaseChannelGroup", GlobalEventExecutor.INSTANCE);
	
	private static final Map<String, ChannelGroup> APP_MAP = new ConcurrentHashMap<String, ChannelGroup>();
	
	private static final Map<Channel, String> APP_CHANNEL_MAP = new ConcurrentHashMap<Channel, String>();
	
	private static final Map<String, Channel> APP_CHANNEL = new ConcurrentHashMap<String, Channel>();
	
	public static void add(String userId, Channel channel) {
		logger.info("addChannel=======userId[{}], channel[{}]", userId, channel);
		logger.info("addChannel====channel is null ?" + (APP_CHANNEL.get(userId) == null));
		logger.info("addChannel==== channel group's size" + (APP_MAP.get(userId) == null ? 0 : APP_MAP.get(userId).size()));
		APP_CHANNEL_GROUP.add(channel);
		APP_CHANNEL_MAP.put(channel, userId);
		APP_CHANNEL.put(userId, channel);
		if(APP_MAP.containsKey(userId)) {
			APP_MAP.get(userId).add(channel);
		}else{
			ChannelGroup channelGroup = new DefaultChannelGroup(userId, GlobalEventExecutor.INSTANCE);
			channelGroup.add(channel);
			APP_MAP.put(userId, channelGroup);
		}
	}
	
	public static ChannelGroupFuture broadcast(String userId, Object msg) {
		
		logger.info("broadcast====userid[{}] app_channel is null {}", userId , APP_CHANNEL.get(userId) == null);
		if(APP_MAP.get(userId) != null) {
			logger.info("app_channel_map.size: {}", APP_MAP.get(userId).size());
			APP_MAP.get(userId).writeAndFlush(new TextWebSocketFrame((String)msg));
		}
		return null;
	}
	
	public static ChannelGroupFuture broadcast(String userId, Object msg, ChannelMatcher matcher) {
//		if(BOOKCASE_MAP.get(bookcaseId) != null) 
//			return BOOKCASE_MAP.get(bookcaseId).writeAndFlush(new TextWebSocketFrame((String)msg), matcher);
		if(APP_CHANNEL.get(userId) != null)
			 APP_CHANNEL.get(userId).writeAndFlush(new TextWebSocketFrame((String)msg));
		return null;
	}
	
	public static ChannelGroup flush(String userId) {
		return APP_MAP.get(userId).flush();
	}
	
	public static boolean discard(Channel channel) {
		String bookcaseId = APP_CHANNEL_MAP.remove(channel);
		logger.info("discardChannel===== userId[{}], channel[{}]", bookcaseId, channel);
		APP_MAP.get(bookcaseId).remove(channel);
		APP_CHANNEL.remove(bookcaseId);
		return APP_CHANNEL_GROUP.remove(channel);
	}
	
	public static boolean discard(String userId, Channel channel) {
		
		APP_CHANNEL_MAP.remove(channel);
		APP_MAP.get(userId).remove(channel);
		return APP_CHANNEL_GROUP.remove(channel);
	}
	
	public static ChannelGroupFuture disconnect() {
		return APP_CHANNEL_GROUP.disconnect();
	}
	
	public static ChannelGroupFuture disconnect(String userId) {
		return APP_MAP.get(userId).disconnect();
	}
	
	public static ChannelGroupFuture disconnect(ChannelMatcher matcher) {
		return APP_CHANNEL_GROUP.disconnect(matcher);
	}
	
	public static ChannelGroupFuture disconnect(String userId, ChannelMatcher matcher) {
		return APP_MAP.get(userId).disconnect(matcher);
	}
	
	public static boolean contains(Channel channel) {
		return APP_CHANNEL_GROUP.contains(channel);
	}
	
	public static String getBookCaseId(Channel channel) {
		return APP_CHANNEL_MAP.get(channel);
	}
}
